package com.yzq.controller;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yzq.annotation.AuthCheck;
import com.yzq.api.aliyunai.AliyunApiAi;
import com.yzq.api.aliyunai.enums.ImageEditFunction;
import com.yzq.api.aliyunai.model.AIResponse;
import com.yzq.api.imageSearch.SoImageSearchApiFacade;
import com.yzq.api.imageSearch.model.SoImageSearchResult;
import com.yzq.common.Result;
import com.yzq.constant.UserConstant;
import com.yzq.enums.ErrorCode;
import com.yzq.manager.auth.annotation.SaSpaceCheckPermission;
import com.yzq.manager.auth.model.SpaceUserPermissionConstant;
import com.yzq.model.dto.picture.*;
import com.yzq.model.entity.Picture;
import com.yzq.model.vo.PictureVO;
import com.yzq.service.PictureService;
import com.yzq.utils.ThrowUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Api(tags = "图片管理")
@RequestMapping("/picture")
@RestController
public class PictureController {

    @Resource
    private PictureService pictureService;

    @Resource
    private StringRedisTemplate  stringRedisTemplate;

    @Resource
    private AliyunApiAi aliyunApiAi;



    /**
     * 图片上传到阿里云（临时）
     * @param file 图片文件
     *@return 图片上传结果: url 地址
     */
    @PostMapping("/upload/temp")
    @ApiOperation("图片上传到阿里云（临时）")
    public Result<String> uploadPictureToAliyun(@RequestPart("file") MultipartFile file) throws Exception {
        return Result.success(pictureService.uploadPictureToAliyun(file));
    }

    /**
     * 上传图片
     * @param file 图片文件
     * @param pictureUploadRequest 图片上传请求
     * @param request 请求对象
     * @return 图片信息
     * @throws Exception 当上传过程中出现异常时抛出
     */
    @PostMapping("/upload")
    @ApiOperation("上传图片")
    @SaSpaceCheckPermission(value = SpaceUserPermissionConstant.PICTURE_UPLOAD)
    public Result<PictureVO> uploadPicture(@RequestPart("file") MultipartFile file,PictureUploadRequest pictureUploadRequest, HttpServletRequest request) throws Exception {
        log.info("file: {}", file);
        log.info("上传图片开始: {}", pictureUploadRequest);
        return Result.success(pictureService.uploadPicture(file,pictureUploadRequest, request));
    }

    /**
     * 上传图片
     * @param pictureUrlUploadRequest 图片上传请求
     * @param request 请求对象
     * @return 图片信息
     * @throws Exception 当上传过程中出现异常时抛出
     */
    @PostMapping("/upload/url")
    @ApiOperation("上传图片url")
    @SaSpaceCheckPermission(value = SpaceUserPermissionConstant.PICTURE_UPLOAD)
    public Result<PictureVO> uploadPictureByUrl(@RequestBody PictureUrlUploadRequest pictureUrlUploadRequest, HttpServletRequest request) throws Exception {
        log.info("url上传图片开始: {}", pictureUrlUploadRequest);
        return Result.success(pictureService.uploadPictureByUrl(pictureUrlUploadRequest, request));
    }

    /**
     * 删除图片
     * @param pictureDeleteRequest 图片删除请求
     * @return 删除结果
     */
    @ApiOperation("删除图片")
    @DeleteMapping("/delete")
    @SaSpaceCheckPermission(value = SpaceUserPermissionConstant.PICTURE_DELETE)
    public Result<Boolean> deletePicture(@RequestBody PictureDeleteRequest pictureDeleteRequest, HttpServletRequest request) {
        log.info("删除图片开始: {}", pictureDeleteRequest);
        return Result.success(pictureService.deletePicture(pictureDeleteRequest,  request));
    }

    /**
     * 修改图片
     * @param pictureUpdateRequest 图片修改请求
     * @return 修改结果
     */
    @ApiOperation("修改图片")
    @PutMapping("/update")
    @SaSpaceCheckPermission(value = SpaceUserPermissionConstant.PICTURE_EDIT)
    public Result<Boolean> updatePicture(@RequestBody PictureUpdateRequest pictureUpdateRequest, HttpServletRequest request) {

        log.info("修改图片开始: {}", pictureUpdateRequest);
        return Result.success(pictureService.updatePicture(pictureUpdateRequest, request));
    }

    /**
     * 获取图片分页列表
     * @param pictureQueryRequest 图片查询请求
     * @return 图片分页列表
     */
    @ApiOperation("获取图片分页列表")
    @GetMapping("/list")
    public Result<Page<PictureVO>> getPictureList(PictureQueryRequest pictureQueryRequest) {
        log.info("获取图片分页列表开始: {}", pictureQueryRequest);
        Long spaceId = pictureQueryRequest.getSpaceId();
        //公开图库
        if(spaceId == null) {
            pictureQueryRequest.setNullSpaceId(true);
        }
        return Result.success(pictureService.getPictureList(pictureQueryRequest));
    }


    /**
     * 获取图片分页列表 - redis
     * @param pictureQueryRequest 图片查询请求
     * @return 图片分页列表
     */
    @ApiOperation("获取图片分页列表")
    @GetMapping("/list/redis")
    public Result<Page<PictureVO>> getPictureListRedis(PictureQueryRequest pictureQueryRequest) {
        log.info("获取图片分页列表开始: {}", pictureQueryRequest);
        // 构建缓存 key
        String jsonStr = JSONUtil.toJsonStr(pictureQueryRequest);
        String s = DigestUtils.md5DigestAsHex(jsonStr.getBytes());
        String key = "picture:query:redis:" + s;

        // 从redis 中获取缓存数据
        ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
        String picture = stringStringValueOperations.get(key);
        if (picture != null) {
            Page<PictureVO> bean = JSONUtil.toBean(picture, Page.class);
            return Result.success(bean);
        }

        Page<PictureVO> pictureList = pictureService.getPictureList(pictureQueryRequest);

        // 写入缓存
        String jsonStr1 = JSONUtil.toJsonStr(pictureList);
        // 缓存 5 - 10  分钟
        int expire = 300 + RandomUtil.randomInt(0,300);
        stringStringValueOperations.set(key, jsonStr1, expire, TimeUnit.SECONDS);

        return Result.success();
    }

    /**
     * 管理员获取图片列表
     * @param pictureQueryRequest 图片查询参数
     * @return 图片列表
     */
    @ApiOperation("管理员获取图片列表")
    @GetMapping("/list/admin")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    public Result<Page<Picture>> getPictureListAdmin(PictureQueryRequest pictureQueryRequest) {
        log.info("管理员获取图片分页列表开始: {}", pictureQueryRequest);
        Long spaceId = pictureQueryRequest.getSpaceId();
        //公开图库
        if(spaceId == null) {
            pictureQueryRequest.setNullSpaceId(true);
        }
        return Result.success(pictureService.getPictureListByAdmin(pictureQueryRequest));
    }


    /**
     * 根据 id 获取图片信息
     * @param id 图片 id
     * @return 图片信息
     */
    @ApiOperation("根据 id 获取图片信息")
    @GetMapping("/get")
    public Result<PictureVO> getPictureById(Long id, HttpServletRequest request) {
        log.info("根据 id 获取图片信息开始: {}", id);
        return Result.success(pictureService.getPictureById(id, request));
    }

    /**
     * 审核图片
     * @param pictureReviewRequest 图片审核请求
     * @return 审核结果
     */
    @ApiOperation("审核图片")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    @PostMapping("/review")
    public Result<Boolean> reviewPicture(@RequestBody PictureReviewRequest pictureReviewRequest, HttpServletRequest request) {
        log.info("审核图片开始: {}", pictureReviewRequest);
        return Result.success(pictureService.reviewPicture(pictureReviewRequest, request));
    }

    /**
     *  批量上传图片
     * @param pictureUploadByBatchRequest 图片上传参数
     * @param request 请求
     * @return 图片数量
     */
    @ApiOperation("批量抓取图片")
    @AuthCheck(mustRole = UserConstant.ADMIN_ROLE)
    @PostMapping("/upload/batch")
    public Result<Integer> uploadPictureByBatch(@RequestBody PictureUploadByBatchRequest pictureUploadByBatchRequest, HttpServletRequest request) throws Exception {
        log.info("开始批量抓取图片");
        return Result.success(pictureService.uploadPictureByBatch(pictureUploadByBatchRequest, request));
    }

    /**
     * 下载图片
     * @param pictureDownloadRequest 图片下载参数
     * @param request 请求
     */
    @ApiOperation("下载图片")
    @PostMapping("/download")
    public Result<String> downloadPicture(@RequestBody PictureDownloadRequest pictureDownloadRequest, HttpServletRequest request) {
        log.info("开始下载图片");
        pictureService.downloadPicture(pictureDownloadRequest, request);
        return Result.success("下载成功");
    }

    /**
     * 以图搜图
     */
    @ApiOperation("以图搜图")
    @PostMapping("/search/picture/so")
    public Result<List<SoImageSearchResult>> searchPictureByPictureIsSo(@RequestBody SearchPictureByPictureRequest searchPictureByPictureRequest) {
        ThrowUtils.throwIf(searchPictureByPictureRequest == null, ErrorCode.BAD_REQUEST);
        Long pictureId = searchPictureByPictureRequest.getPictureId();
        ThrowUtils.throwIf(pictureId == null || pictureId <= 0, ErrorCode.BAD_REQUEST);
        Picture oldPicture = pictureService.getById(pictureId);
        ThrowUtils.throwIf(oldPicture == null, ErrorCode.NOT_FOUND);
        List<SoImageSearchResult> resultList = new ArrayList<>();
        // 这个 start 是控制查询多少页, 每页是 20 条
        int start = 0;
        while (resultList.size() <= 50) {
            List<SoImageSearchResult> tempList = SoImageSearchApiFacade.searchImage(
                   oldPicture.getUrl(), start
            );
            if (tempList.isEmpty()) {
                break;
            }
            resultList.addAll(tempList);
            start += tempList.size();
        }
        return Result.success(resultList);
    }


    /**
     * 批量修改图片
     * @param pictureEditByBatchRequest 图片修改参数
     * @param request 请求
     * @return 修改结果
     */
    @ApiOperation("批量修改图片")
    @PostMapping("/edit/batch")
    @SaSpaceCheckPermission(value = SpaceUserPermissionConstant.PICTURE_EDIT)
    public Result<Boolean> editPictureByBatch(@RequestBody PictureEditByBatchRequest pictureEditByBatchRequest, HttpServletRequest request) {
        log.info("开始批量修改图片:{}", pictureEditByBatchRequest);
        ThrowUtils.throwIf(pictureEditByBatchRequest == null, ErrorCode.BAD_REQUEST);
        pictureService.editPictureByBatch(pictureEditByBatchRequest, request);
        return Result.success(true);
    }

    /**
     * 创建AI文生图任务
     * @param textToImageRequest AI文生图请求
     * @return 任务id
     */
    @ApiOperation("创建AI文生图任务")
    @PostMapping("/create/text/to/image/task")
    public Result<String> CreateTextToImageTask(@RequestBody TextToImageRequest textToImageRequest) {
        log.info("开始创建图片转文字任务:{}", textToImageRequest);
        ThrowUtils.throwIf(textToImageRequest == null, ErrorCode.BAD_REQUEST);
        String s = pictureService.createTextToImageTask(textToImageRequest);
        return Result.success(s);
    }

    /**
     * 创建AI图片编辑任务
     */
    @ApiOperation("创建AI图片编辑任务")
    @PostMapping("/create/picture/edit/task")
    public Result<String> createPictureEditTask(@RequestBody AIImageEditRequest pictureEditRequest) {
        log.info("开始创建图片编辑任务:{}", pictureEditRequest);
        ThrowUtils.throwIf(pictureEditRequest == null, ErrorCode.BAD_REQUEST);
        return Result.success(pictureService.createPictureEditTask(pictureEditRequest));
    }

    @ApiOperation("获取AI编辑模型列表")
    @GetMapping("/get/ai/edit/model/list")
    public Result<List<String>> getAIModelList() {
        log.info("开始获取AI模型列表");
        ImageEditFunction[] values = ImageEditFunction.values();
        return Result.success(Arrays.stream(values).map(ImageEditFunction::getFunctionName).toList());
    }

    @ApiOperation("获取AI任务结果")
    @GetMapping("/get/text/to/image/task/result")
    public Result<AIResponse> getTextToImageTaskResult(@RequestParam String taskId) {
        log.info("开始获取AI任务结果:{}", taskId);
        ThrowUtils.throwIf(taskId == null, ErrorCode.BAD_REQUEST);
        AIResponse textToImageResult = aliyunApiAi.getTextToImageResult(taskId);
        return Result.success(textToImageResult);
    }

}
